#include "DrawScene.h"
#include "Scene.h"

#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define POS(a) MAX(a, 0)

using namespace CG;
using namespace LA;

void DrawAxis::draw(Scene *scene)
{
    // 开启虚线绘制
    glEnable(GL_LINE_STIPPLE);
    glLineStipple(1, 0xff);

    // 绘制坐标轴
    glColor3f(1, 0, 0);
    glBegin(GL_LINES);
    glVertex3f(0, 0, 0);
    glVertex3f(1000, 0, 0);
    glEnd();

    glColor3f(0, 1, 0);
    glBegin(GL_LINES);
    glVertex3f(0, 0, 0);
    glVertex3f(0, 1000, 0);
    glEnd();

    glColor3f(0, 0, 1);
    glBegin(GL_LINES);
    glVertex3f(0, 0, 0);
    glVertex3f(0, 0, 1000);
    glEnd();

    // 重置颜色
    glColor3f(1, 1, 1);
    glDisable(GL_LINE_STIPPLE);
}

void DrawMesh::draw(Scene *scene)
{
    // 设置显示模式
    glPolygonMode(scene->m_data.face, scene->m_data.mode);

    // 注意这几步不能合并
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_COLOR_ARRAY);

    // 绘制所有网格
    for (int k = 0; k < scene->m_mList.size(); k++)
    {
        Mesh *mesh = scene->m_mList[k];

        // 按顺序标记顶点
        for (int i = 0; i < mesh->VertexNum(); i++)
            mesh->m_vList[i]->identity = i;

        // 输出所有顶点和颜色信息
        int count = mesh->VertexNum();
        float *arrayv = new float[count * 3];
        for (int i = 0; i < mesh->VertexNum(); i++)
        {
            arrayv[3 * i + 0] = mesh->m_vList[i]->pos.x;
            arrayv[3 * i + 1] = mesh->m_vList[i]->pos.y;
            arrayv[3 * i + 2] = mesh->m_vList[i]->pos.z;
        }
        // 注册顶点数组
        glVertexPointer(3, GL_FLOAT, 3 * sizeof(GLfloat), arrayv);

        // 注册颜色数组
        float *arrayc = new float[count * 3];
        for (int i = 0; i < mesh->VertexNum(); i++)
        {
            arrayc[3 * i + 0] = mesh->m_cList[i].r;
            arrayc[3 * i + 1] = mesh->m_cList[i].g;
            arrayc[3 * i + 2] = mesh->m_cList[i].b;
        }
        // 注册颜色数组
        glColorPointer(3, GL_FLOAT, 3 * sizeof(GLfloat), arrayc);

        count = mesh->FaceNum();
        int *index = new int[count * 3];

        // 遍历网格面，依次输出每个面的顶点位置
        for (int i = 0; i < mesh->FaceNum(); i++)
        {
            std::deque<vertex3f *> v = mesh->VertexOnFace(mesh->m_fList[i]);
            index[3 * i + 0] = v[0]->identity;
            index[3 * i + 1] = v[1]->identity;
            index[3 * i + 2] = v[2]->identity;
        }

        // 绘制所有三角形
        glDrawElements(GL_TRIANGLES, mesh->FaceNum() * 3, GL_UNSIGNED_INT, index);

        // 销毁数据
        delete[] index;
        delete[] arrayc;
        delete[] arrayv;
    }
}

void DrawBox::draw(Scene *scene)
{
    // 没有选中，直接返回
    if (scene->m_data.choose == -1)
        return;

    bounding_box box = scene->m_mList[scene->m_data.choose]->m_box;

    glEnable(GL_LINE_STIPPLE);
    glLineStipple(1, 0xff);

    // 绘制 6 个面
    glBegin(GL_LINE_LOOP);
    glVertex3f(box.left, box.top, box.zFar);
    glVertex3f(box.left, box.bottom, box.zFar);
    glVertex3f(box.left, box.bottom, box.zNear);
    glVertex3f(box.left, box.top, box.zNear);
    glEnd();

    glBegin(GL_LINE_LOOP);
    glVertex3f(box.left, box.top, box.zNear);
    glVertex3f(box.left, box.bottom, box.zNear);
    glVertex3f(box.right, box.bottom, box.zNear);
    glVertex3f(box.right, box.top, box.zNear);
    glEnd();

    glBegin(GL_LINE_LOOP);
    glVertex3f(box.right, box.top, box.zNear);
    glVertex3f(box.right, box.bottom, box.zNear);
    glVertex3f(box.right, box.bottom, box.zFar);
    glVertex3f(box.right, box.top, box.zFar);
    glEnd();

    glBegin(GL_LINE_LOOP);
    glVertex3f(box.right, box.top, box.zFar);
    glVertex3f(box.right, box.bottom, box.zFar);
    glVertex3f(box.left, box.bottom, box.zFar);
    glVertex3f(box.left, box.top, box.zFar);
    glEnd();

    glBegin(GL_LINE_LOOP);
    glVertex3f(box.right, box.top, box.zFar);
    glVertex3f(box.left, box.top, box.zFar);
    glVertex3f(box.left, box.top, box.zNear);
    glVertex3f(box.right, box.top, box.zNear);
    glEnd();

    glBegin(GL_LINE_LOOP);
    glVertex3f(box.right, box.bottom, box.zFar);
    glVertex3f(box.right, box.bottom, box.zNear);
    glVertex3f(box.left, box.bottom, box.zNear);
    glVertex3f(box.left, box.bottom, box.zFar);
    glEnd();

    glDisable(GL_LINE_STIPPLE);
}
